﻿using System;
using System.Collections.Generic;
using CI.Interfaces;
using CI.Mesopotamia.WebService;
using CI.Misc;
using CI.WebService;

namespace CI.Mesopotamia
{
    /// <summary>
    /// Grid based scenario
    /// </summary>
    public class ScenarioGrid : Scenario
    {
        /// <summary>
        /// Load a scenario
        /// </summary>
        public override void Load()
        {

            SimEnv.TraceLogger.LogDebug("Grid Scenario Load - start");
            // client connection to server
            var ibc = new InboundClient();
#if (DEBUG&&GRIDLOCAL)
            // if debug use the local endpoint for debugging
            ibc.Endpoint.Address = new System.ServiceModel.EndpointAddress("http://localhost/MesopotamiaDCProxy/inbound.svc");
#endif
            // result
            IScenario result = null;
            // scenario in xml
            var localXml = new ScenarioLocalXML();

            try
            {
                // get the scenario
                result = ibc.LoadScenario(ScenarioName, Properties.Settings.Default.UserID);

                // copy to this
                if (result != null)
                    CopyScenario(result, this);
            }
            catch (System.ServiceModel.EndpointNotFoundException)
            {
                // not connected so exit
                SimEnv.TraceLogger.LogDebug("Unable to connect to grid to load scenario");
            }
            catch (Exception ex)
            {
                // not connected so exit
                SimEnv.TraceLogger.LogDebug("Exception loading scenario : " + ex.Message);
            }
            finally
            {
                ibc.Close();
            }

            // if we were unable to connect to the server try the xml dal
            if (result == null)
            {
                // load scenario from xml
                LoadScenarioFromXML(localXml);
            }
            else
            // else lets save the latest version of the scenario to the xml for later use
            {
                ArchiveScenarioToXML(localXml);
            }

            SimEnv.TraceLogger.LogDebug("Grid Scenario Load - Finish");

        }

        private void ArchiveScenarioToXML(ScenarioLocalXML localXml)
        {
            SimEnv.TraceLogger.LogDebug("ArchiveScenarioToXML");
            CopyScenario(this, localXml);
            localXml.Save();
        }

        private void LoadScenarioFromXML(ScenarioLocalXML localXml)
        {
            SimEnv.TraceLogger.LogDebug("LoadScenarioFromXML");
            localXml.ScenarioName = ScenarioName;
            localXml.Load();

            // copy result to here
            CopyScenario(localXml, this);
        }

        /// <summary>
        /// get list of available scenarios
        /// </summary>
        /// <returns></returns>
        public override IEnumerable<string> GetScenariosAvailable()
        {
            var result = new List<string>();

            SimEnv.TraceLogger.LogDebug("Grid GetScenariosAvailable - Start");

            // see if we can get the server            
            var ibc = new InboundClient();
#if (DEBUG&&GRIDLOCAL)
            // if debug use the local endpoint for debugging
            ibc.Endpoint.Address = new System.ServiceModel.EndpointAddress("http://localhost/MesopotamiaDCProxy/inbound.svc");
#endif
            try
            {
                SimEnv.TraceLogger.LogDebug("Please wait, communicating  with grid");

                result = new List<string>(ibc.GetScenarioList(HostingEnvironmentVersionInformation, Properties.Settings.Default.UserID));
            }
            catch (System.ServiceModel.EndpointNotFoundException)
            {
                // not connected so exit
                SimEnv.TraceLogger.LogDebug("Unable to connect to grid");
            }
            catch (Exception ex)
            {
                // not connected so exit
                SimEnv.TraceLogger.LogException("Exception getting list", ex);
            }
            finally
            {
                ibc.Close();
            }

            SimEnv.TraceLogger.LogDebug(string.Format("Scenarios Found : {0}", result.Count));
            SimEnv.TraceLogger.LogDebug("Grid GetScenariosAvailable - Finish");
            return result;
        }

        /// <summary>
        /// get list of available scenarios
        /// </summary>
        /// <returns></returns>
        public override ScenarioOrganismCollection GetScenarioOrganisms(string scenarioName, int startIndex, int endIndex)
        {
            ScenarioOrganismCollection result = null;

            SimEnv.TraceLogger.LogDebug("Grid GetScenarioOrganisms - Start");

            // see if we can get the server            
            var ibc = new InboundClient();
            //ibc.InnerChannel.OperationTimeout
#if (DEBUG&&GRIDLOCAL)
            // if debug use the local endpoint for debugging
            ibc.Endpoint.Address = new System.ServiceModel.EndpointAddress("http://localhost/MesopotamiaDCProxy/inbound.svc");
#endif
            try
            {
                SimEnv.TraceLogger.LogDebug("Please wait, communicating  with grid");
                result = ibc.GetScenarioOrganisms(scenarioName, startIndex, endIndex);
            }
            catch (System.ServiceModel.EndpointNotFoundException)
            {
                // not connected so exit
                SimEnv.TraceLogger.LogDebug("Unable to connect to grid");
            }
            catch (Exception ex)
            {
                // not connected so exit
                SimEnv.TraceLogger.LogException("Exception getting list", ex);
            }
            finally
            {
                ibc.Close();
            }

            SimEnv.TraceLogger.LogDebug("Grid GetScenarioOrganisms - Finish");
            return result;
        }

        /// <summary>
        /// Can we connect to the grid
        /// </summary>
        /// <returns></returns>
        public static bool GridOnline()
        {

            SimEnv.Instance.TraceLogger.LogDebug("GridOnline - Start");

            // see if we can get the server            
            InboundClient ibc = null;
            var result = false;
            var quickConnect = new TimeSpan(0, 0, 0, 5);

            try
            {
                ibc = new InboundClient();

                ibc.Endpoint.Binding.SendTimeout = quickConnect;
                ibc.Endpoint.Binding.OpenTimeout = quickConnect;
                ibc.Endpoint.Binding.ReceiveTimeout = quickConnect;
                ibc.Endpoint.Binding.CloseTimeout = quickConnect;

#if (DEBUG&&GRIDLOCAL)
                // if debug use the local endpoint for debugging
                ibc.Endpoint.Address = new System.ServiceModel.EndpointAddress("http://localhost/MesopotamiaDCProxy/inbound.svc");
#endif
                // get a number and make sure it increments it
                var testNumber = new Random().Next();
                SimEnv.Instance.TraceLogger.LogDebug("Please wait, communicating  with grid : " + ibc.Endpoint.Address);

                if ((testNumber + 1) == ibc.Increment(testNumber))
                {
                    // check and make sure got a user id else ask for it
                    if (Properties.Settings.Default.UserID == 0)
                    {
                        Properties.Settings.Default.UserID = ibc.GetNewUserId(Environment.MachineName, new MSRBHost(new MockHostingEnvironmentPhysical(), new ScenarioGrid()).VersionInformation);
                        Properties.Settings.Default.Save();
                    }
                    result = true;
                }
            }
            catch (System.ServiceModel.EndpointNotFoundException)
            {

                // not connected so exit
                SimEnv.Instance.TraceLogger.LogDebug("Unable to connect to grid");
                result = false;
            }
            catch (Exception ex)
            {
                // not connected so exit
                SimEnv.Instance.TraceLogger.LogDebug("Exception testing Grid online :" + ex.Message);
                result = false;
            }
            finally
            {
                if (ibc != null)
                    ibc.Close();
            }

            SimEnv.Instance.TraceLogger.LogDebug(string.Format("GridOnline - State : {0}", result));
            SimEnv.Instance.TraceLogger.LogDebug("GridOnline - Finish");
            return result;
            //return false;
        }
    }
}